home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d7
/
jmodm308.arc
/
JMODEM_C.DOC
< prev
next >
Wrap
Text File
|
1991-01-02
|
45KB
|
1,181 lines
J M O D E M
* The Microsoft C Version *
January 2, 1991
Richard B. Johnson
405 Broughton Drive
Beverly Massachusetts 01915
BBS (508) 922-3166
Introduction.
JMODEM was first introduced about two years ago. It has en-
joyed a steady increase in popularity around the world. It
has even been explained in some detail in John Dvorak's book
on PC communications; Dvorak's Guide to PC Telecommunica-
tions, 1990, Osborne-McGraw-Hill, 2600 Tenth Street,
Berkeley, CA.
JMODEM was first written in assembly language. Since this
language is hard to read and use, it has been difficult for
communications program developers to incorporate it into
their programs directly. Instead it must be executed as an
external protocol. Now JMODEM has been written in the C
Language. C has become the de-facto standard for portable
code development even though there isn't presently any code
that is truly portable across many different machines. The
writing of JMODEM in C will make it easier for software de-
velopers throughout the world to use this very useful pro-
tocol.
You can use this new version of JMODEM just as the older
versions written in assembly. It has a new color sign-on
screen and status-block windows that overlap. Although the
new JMODEM.EXE code is larger than the assembly-language
version, JMODEM.COM, the program still executes very fast
because much effort has been taken to streamline the C code.
JMODEM.COM required 64 k of RAM (one segment) to execute
properly. JMODEM.EXE requires 79 k to allow the screens to
be written properly, and 66 k of free RAM to execute without
aborting although the previous screen content will be lost.
Like all versions of JMODEM, this version is 100% compatible
with all previous version including Beta version 1.00. From
it's inception, the essential structure of JMODEM has never
been changed.
How to install JMODEM.
JMODEM executes best from a batch file as an external pro-
tocol for any of the communications programs that have ex-
ternal-protocol capability. A typical communications program
is TELIX.
- 1 -
JMODEM, the C Version
Here is a batch file used with TELIX for uploads:
@ECHO OFF
Rem * JMODEM TELIX Upload batch file.
C:\TELIX\JMODEM S1 %3
Rem | || |_________ file name (passed by TELIX)
Rem | ||____________ COM port (1 - 4)
Rem | |_____________ Send
Rem |_______________ Path and name of JMODEM
This is a batch file used with TELIX for downloads:
@ECHO OFF
Rem * JMODEM TELIX Download batch file.
C:\TELIX\JMODEM R1 %3
Rem | || |_________ file name (passed by TELIX)
Rem | ||____________ COM port (1 - 4)
Rem | |_____________ Receive
Rem |_______________ Path and name of JMODEM
This is a batch file used for PCPLUS (PROCOMM) uploads:
@ECHO OFF
Rem * JMODEM PCPLUS Upload batch file.
C:\TELIX\JMODEM S1 %1
Rem | || |_________ file name (passed by PCPLUS)
Rem | ||____________ COM port (1 - 4)
Rem | |_____________ Send
Rem |_______________ Path and name of JMODEM
This is a batch file for PCPLUS (PROCOMM) ownloads:
@ECHO OFF
Rem * JMODEM PCPLUS Download batch file.
C:\TELIX\JMODEM R1 %1
Rem | || |_________ file name (passed by PCPLUS)
Rem | ||____________ COM port (1 - 4)
Rem | |_____________ Receive
Rem |_______________ Path and name of JMODEM
- 2 -
JMODEM, the C Version
If I wished to receive in the "batch" mode, I could make a
file like this. Notice that some communications programs do
not allow multiple file names. Note that the comments "!"
are NOT ALLOWED in a DOS batch file.
:DO_LOOP ! Return here
IF "%3" == "" GOTO DONE ! More parameters?
C:\TELIX\JMODEM R1 %3 ! Execute JMODEM
IF ERRORLEVEL 1 GOTO DONE ! Abort on error
SHIFT ! %4 becomes %3
GOTO DO_LOOP ! Continue
:DONE ! Exit batch file
If you do not know what "%" parameters are used to pass the
file name, all you have to do is make a "dummy" batch file
that contains the following:
@ECHO OFF
ECHO %1
ECHO %2
ECHO %3
ECHO %4
ECHO %5
PAUSE
When this is executed, you will see something like this:
1200
1
FILENAME.TYP
ECHO is off
ECHO is off
Strike a key when ready . . .
The first line contains "1200" which is the baud rate. This
means that the %1 parameter contains the baud rate.
The second line contains "1" which is the communications
adapter port being used. This means that the port is being
passed as the %2 parameter.
The third line contains "FILENAME.TYP" which is the file
name. This means that the file name is being passed as the
%3 parameter.
The fourth and fifth lines contain nothing to echo so DOS
replies the current state of the echo function which is
"off".
PCPLUS handles the file name passing a little bit different.
If I execute the same "dummy" batch file from the PCPLUS
directory, the response is:
- 3 -
JMODEM, the C Version
FILENAME.TYP
ECHO is off
ECHO is off
ECHO is off
ECHO is off
Strike a key when ready . . .
This shows us that PCPLUS passes the file name as the first
parameter and there are no other parameters. However, If I
put more parameters on the command line within PCPLUS, they
will get sent to the batch file. The response is:
FILENAME.001
FILENAME.002
FILENAME.003
FILENAME.
ECHO is off
Strike a key when ready . . .
Therefore PCPLUS allows up to four file names to be passed
providing there's room on the command line.
Notice that these two communications programs check the
default directory for the external protocol batch file
FIRST! Therefore you must make certain that there are no
other similarly-named batch files in the current directory
or within the current path. Failure to do so will cause the
improper execution of the wrong batch file. Lets say that
the path was "C:\DOS;C:\TOOLS;C:\PCPLUS;C:\TELIX;C:\QMODEM".
If you named all your JMODEM external protocol batch files
with the same name, and you were attempting to use an ex-
ternal file transfer protocol from QMODEM, the batch file
designed to operate with PCPLUS would be the first one
"found" and executed since the search-path will search the
\PCPLUS directory before the \QMODEM directory. You prevent
the execution of the incorrect batch file by calling them
slightly different names.
When setting up external protocols, remember to configure
the communications program so that it prompts you for the
file names. Unlike some protocols, JMODEM does not transfer
the file name. You can use any file name that you wish. You
must pass the file name to JMODEM since it must know the
name of the file being transmitted or received. There are no
defaults.
- 4 -
JMODEM, the C Version
Setting up a BBS System
External File-Transfer Protocol.
If you are running a WILDCAT! bulletin board, the external
protocol files can be set up like this:
(JUP.BAT)
CD D:\WILDCAT\PROTOCOL
IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
JMODEM R1 %3
IF ERRORLEVEL 1 GOTO END
COPY %3 %4
:END
DEL %3
(JDOWN.BAT)
CD D:\WILDCAT\PROTOCOL
IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
JMODEM S1 %3
IF ERRORLEVEL 1 GOTO BAD
GOTO END
:BAD
COPY ALL.OK TRANSFER.BAD
:END
There are many variations available. Since WILDCAT! supports
batch-mode downloading, you could set up the batch file like
this:
(JDOWN.BAT)
CD D:\WILDCAT\PROTOCOL
IF EXIST TRANSFER.BAD DEL TRANSFER.BAD
:DO_LOOP
IF "%3" == "" GOTO END
JMODEM S1 %3
IF ERRORLEVEL 1 GOTO BAD
SHIFT
GOTO DO_LOOP
:BAD
COPY ALL.OK TRANSFER.BAD
:END
WILDCAT! checks the \PROTOCOL directory to see if the file
TRANSFER.BAD has been created. If it exists, it announces
that the file transfer has failed. It also announces "Error
with external protocol .. ". It does this when, in fact,
WILDCAT! has made an error itself. In many cases WILDCAT!
will "find" the file TRANSFER.BAD when it DOES NOT EXIST! In
spite of this bug, WILDCAT! is one of the most reliable BBS
systems supporting external protocols.
- 5 -
JMODEM, the C Version
When setting up batch files remember that there is also a
bug in all DOS versions. The "IF ERRORLEVEL " statement does
NOT test the actual value of ERRORLEVEL! Instead it checks
to see if the returned value is EQUAL or GREATER than the
tested value. If you were to put the statement:
IF ERRORLEVEL 0 GOTO GOOD
.... in a batch file, the execution would ALWAYS branch to
label "GOOD" regardless of the actual ERRORLEVEL returned!
JMODEM does not require any information about handshaking.
It will look at the modem port and figure out for itself
what to do.
In the event that the modem carrier is lost, JMODEM will
abort. Since JMODEM only checks the modem port occasionally,
it may take several seconds to abort when the carrier is
lost. It is impossible for a user to get at the DOS level
through JMODEM. Do NOT use the CTTY command in the external
protocol batch files. JMODEM returns ERRORLEVEL 1 if there
was any error in transmission or reception. It returns
ERRORLEVEL 0 (no error) otherwise. It does not delete files
that have been partially received although it properly clos-
es them. The system operator can arrange the batch files to
delete them if required.
When JMODEM attempts to create a file that already exists it
can't ask the user if the old one should be deleted since
the user is probably not in a terminal program at the time.
Therefore, JMODEM renames the other file to <filename.OLD>
and creates the new file. In the event that <filaname.OLD>
exists, it is deleted before the rename operation occurs.
If you don't know what parameters are being sent to external
protocols, you can make a dummy batch file to check them
using the DOS's echo command just as explained in the user
interface previous to this "BBS" section. You can't see the
parameters being echoed from a remote terminal. You must be
present at the BBS board terminal to test those parameters
unless you modify the dummy command file like this:
@ECHO OFF
ECHO %1>COM1
ECHO %2>COM1
ECHO %3>COM1
ECHO %4>COM1
ECHO %5>COM1
If you find that your system passes the file name as %3,
your "upload" (receive) batch file would contain this:
- 6 -
JMODEM, the C Version
JMODEM R1 %3
Your "download" (send) batch file would contain this:
JMODEM S1 %3
In these examples, it is assumed that you are using
communications adapter port "1".
You can chop this text out with an editor and create your
batch files quickly and correctly. PCPLUS passes the file-
name as the %1 parameter and TELIX uses the %3 parameter.
JMODEM does not need to know anything else about your system
to operate. It does not even need to know the baud-rate or
other communications parameters. All it needs to know about
is the file name and the communications adapter port to use.
JMODEM doesn't care if you are using a 19,200 baud modem
with the DTE locked at high-speed or a 300 baud modem on a
lamp-cord. It is very smart about communications and handles
lost carriers (hangup) and flow-control in a very simple way
which will be explained in detail later.
If you only want to try JMODEM without having to install it,
you need only to activate the JMODEM protocol on a BBS sys-
tem, then "shell to DOS" and execute it manually from the
DOS prompt. You will be pleasantly surprised at how rapidly
it can transfer a file and how well it executes over net-
works.
How JMODEM works.
JMODEM uses variable-length records called blocks. These
blocks start with 512 data-bytes and increase in length to a
maximum of 8192 bytes per block. There is a 6-byte overhead
associated with each block so the percentage of overhead
starts at a fairly high 0.1 percent and decreases to a very
low 0.07 percent as the transmission progresses. The block
length will increase in 512-byte increments as long as there
are no errors requiring retransmission. Should an error
occur, the block-size is cut in half. This continues until
the block-size is as short as 64 bytes.
The blocks may actually be of any length but never exceed
the maximum allowed. An attempt is made to reduce the amount
of data that needs to be transmitted by compressing each
block before transmission. Since much data is already com-
pressed, being from ".ZIP" files and such, it is possible
that "compression" may actually cause an increase in block-
length. JMODEM will send a compressed block only if it is
shorter than the non-compressed block.
- 7 -
JMODEM, the C Version
Since it takes time to compress and expand data, only the
simplest and quickest compression method is used. It is very
effective with ".EXE" files that contain large blocks of
binary nulls and most text files but it is not very effec-
tive with highly compressed archive files. The compression
method is called "run-length-limited" or more explicitly
"how many of what kind". Basically, the block is searched
for groups if similar characters. If many similar characters
are found, compression consists of sending a sentinel byte
of hexadecimal BB, followed by a two-byte amount, and this
followed by the byte to be repeated.
In the following example we have a string of spaces (20
hex).
Before compression:
( 18 bytes )
20 20 20 20 20 20 20 20 20 20 20 34 37 87 EF FF 3A 23
After compression:
( 11 bytes )
BB 0B 00 20 34 37 87 EF FF 3A 23
The blocks could actually get longer because the sentinel
byte could be present in the data:
Before compression:
( 9 bytes )
BB 00 BB AF EF BB 00 AE EF
After compression:
( 16 bytes )
BB 01 00 BB 00 BB 01 00 BB AF BB 01 00 BB AE EF
As soon as the encoded length exceeds the data block length,
compression is abandoned and the non-compressed block is
sent. JMODEM sends a byte that tells the receiver if the
data is compressed or not. This same byte tells the receiver
when the end-of-file has occurred so JMODEM is able to
preserve exact file-length.
The JMODEM block.
- 8 -
JMODEM, the C Version
The JMODEM block looks like this:
|< --------- First byte sent / received
20 00 01 01 .. .. .. .. .. AE 01
| | | | | | |___ CRC (high byte)
| | | | | |______ CRC (low byte)
| | | | |_______________ data bytes
| | | |________________________ type of block
| | |___________________________ block number
| |______________________________ block length (high byte)
|_________________________________ block length (low byte)
The Block length:
The block length is a WORD (16 bits). This allows the blocks
to be 65,535 bytes long although in practice the length is
not allowed to exceed 8192 bytes (plus overhead). The block-
length is the length of the entire JMODEM block, not just
the data-bytes.
The Block number:
The block number is a BYTE. It starts at 1 and becomes zero
again after block 255. It is used to make certain that all
receiption errors are detected.
The Block type:
This BYTE is bit-mapped to tell the receiver what kind of
block has been sent. Presently there are three kinds of
blocks:
00000000B Hex 00 ( Normal data )
00000001B Hex 01 ( Compressed data )
00000010B Hex 02 ( End of file )
The CRC:
The CRC is a WORD (16 bits). It is not a "standard" type of
CRC because, unless done with hardware, a standard 16-bit
polynomial would take several seconds to calculate for a
long block. Instead it uses a rapid rotate and sum algorithm
that is probably just as effective as the more "standard"
polynomials.
The CRC is generated using this polynomial:
X = X + X^(2(n-mod 7))....... Where n = t(n-1)
And t = string length
- 9 -
JMODEM, the C Version
It has the advantage of simplicity in assembly-language
programming and will detect errors with a probability of
about one undetected error in 2^132 (which is a very large
number). It does not correct errors so its not important to
use some "standard" function to generate the CRC.
The C code shows how easy it is to create and check this
kind of CRC.
- 10 -
JMODEM, the C Version
The JMODEM Communications
Hardware Control
When JMODEM is first loaded for execution it checks the
state of the modem-control leads. If there is no modem
carrier detected, it assumes that you have connected two PCs
together without a modem and will not bother to check for a
dropped carrier during execution.
Since JMODEM must exercise flow-control so it can be used
with high-speed modems with fixed baud rates, it also as-
sumes that at the time at which it is first executed, the
modem will be requesting data because there will have been
very little I/O over the previous few seconds. JMODEM stores
the state of RTS/CTS and DTR/DSR and uses this as a refer-
ence. When transmitting data, should JMODEM find that the
state of these modem-control leads has changed, it waits
until the modem-control leads have reverted back to the
initial state before sending any more data. This allows ANY
modem to exercise flow-control with JMODEM, even those that
use "pin 4" instead of "pin 20". When JMODEM is waiting, it
checks to verify that the modem carrier has not been drop-
ped. If the carrier is dropped, or if the user aborts,
JMODEM will exit, setting a DOS ERRORLEVEL code.
You can abort JMODEM at any time by hitting Ctrl-Break or
Ctrl-C. It will take several seconds for JMODEM to abort
because it does not continually check these keys. Unlike
previous versions, JMODEM erases the files from aborted
downloads. Also, JMODEM will abort if it is unable to rename
a file in the following example.
Suppose you wish to download a file called VIRUS.EXE. Sup-
pose also that VIRUS.EXE already exists. Instead of over-
writing your previous version of VIRUS.EXE, JMODEM has al-
ways been nice and renamed it to VIRUS.OLD before creating a
new file. With previous versions of JMODEM, if VIRUS.OLD
already existed, JMODEM would have deleted it before renam-
ing the present file to ".OLD". This no longer is done.
JMODEM never deletes ANYTHING anymore except it's own abort-
ed download. This should reduce the number of threats I have
received!
- 11 -
JMODEM, the C Version
The C programmer's
Guide to JMODEM
Included within this package should be the following files:
JMODEM This is a Microsoft MAKE file for JMODEM.EXE.
JMODEMTC Borland's Turbo C MAKE file for JMODEM.EXE.
JMODEM EXE The executable file
JMODEMTC RSP Link response file for Borland's Turbo C
JMODEM_A C Contains the _main() routine entry point.
JMODEM_B C Allocates memory, parses input strings.
JMODEM_C C All of the file I/O is in this file.
JMODEM_D C Data compression/expansion, CRC calculation
JMODEM_E C Communications I/O interrupt service, etc.
JMODEM_F C Screen I/O (windows, etc)
JMODEM H Contains JMODEM globals and data structures.
SCREEN H Screen definitions, prototypes, structures
UART H Definitions for the 8250 UART
TEST C This tests compression /expansion, disk I/O.
TEST This is the Microsoft MAKE file for TEST.EXE
TESTTC Borland's Turbo C MAKE file for TEST.EXE
SHOW C Source for verifying execution in a DOS shell
SHOW Microsoft MAKE file for SHOW.EXE
SHOWTC Borland's Turbo C MAKE file for SHOW.EXE
SHOW EXE Executes JMODEM from a DOS shell.
TEST C Tests JMODEM data-compression and file I/O.
TEST Microsoft MAKE file for TEST.EXE
TESTTC Borland's Turbo C MAKE file for TEST.EXE
TEST EXE Executable to test file I/O and compression
If you have MicroSoft 'C' version 5.0 or later, and if your
environment and paths are properly set up, you should be
able to type:
MAKE JMODEM
... and a brand new version of JMODEM will be created.
If you use Borland's Turbo C, you can use the "TC" make
files to do the same.
Brad Smith from Jacksonville North Carolina created the MAKE
files for Turbo C and modified the source-code to accommo-
date the different libraries used in Turbo C. His revisions
will be present in all subsequent versions of JMODEM to
assure compatibility with Borland's Turbo C.
Brad is a Turbo C guru and runs a BBS system in
Jacksonville.
Brad Smith
141 Riggs Street
Jacksonville, North Carolina 28540
BBS (919) 455-5972 12/24/9600+ 24 hrs
- 12 -
JMODEM, the C Version
With this release, there seems to be a Null-Pointer
assignment error when using Borland's Small Model in TCC
Version 1.5. This is a compiler bug, or more specifically a
bug in the C0.ASM code provided with the compiler that you
can fix.
If you are a Turbo C programmer, don't use the small model
when creating JMODEM.EXE unless you repair the C0.ASM file
and create a new C0S.OBJ file using the MAKE-C0.BAT file
that is provided with the compiler.
To fix the null-pointer problem in Turbo-C find the
following code-fragment in \LIB\C0.ASM provided with your
compiler:
IFNDEF __HUGE__
; Reset un-initialized datas
xor ax, ax
mov es, cs:DGROUP@@
mov di, offset DGROUP: bdata@
mov cx, offset DGROUP: edata@
sub cx, di
rep stosb
ENDIF
Add the following code:
push ds
mov ax,DGROUP
mov ds,ax
mov word ptr ds:[0],0
pop ds
Now find this next code-fragment:
xor ax, ax
mov si, ax
mov cx, lgth_CopyRight
cld
ComputeChecksum label near
add al, [si]
adc ah, 0
inc si
loop ComputeChecksum
sub ax, CheckSum
- 13 -
JMODEM, the C Version
jz ExitToDOS
mov cx, lgth_NullCheck
mov dx, offset DGROUP: NullCheck
call ErrorDisplay
Modify the code so it looks like this:
; xor ax, ax
; mov si, ax
; mov cx, lgth_CopyRight
; cld
;ComputeChecksum label near
; add al, [si]
; adc ah, 0
; inc si
; loop ComputeChecksum
; sub ax, CheckSum
push ds
mov ax,DGROUP
mov ds,ax
cmp word ptr ds:[0],0
pop ds
jz ExitToDOS
mov cx, lgth_NullCheck
mov dx, offset DGROUP: NullCheck
call ErrorDisplay
After to have done this, execute MAKE-C0.BAT for the small
model library from the DOS prompt:
F:\TURBOC\LIB> MAKE-C0 SMALL
This will create a new small-model startup object file.
Just as in the MASM language files, the source code is
strongly-typed. All function prototypes are declared and no
defaults are used. You can compile at warning-level 3, the
most stringent level available with Microsoft compilers, and
you will get no warning errors at all. The default warning
level with Borland's compiler is even more stringent. You
will get a single warning error when compiling TEST.C as the
compiler discovers that dummy parameter "one" in the dummy
screen routine isn't used at all. It has been my experience
that if you get any warnings (in real code), they MUST be
fixed or they will bite you later on.
Example:
*memory++ = foo;
- 14 -
JMODEM, the C Version
... will bump the memory pointer after you put foo
into memory. Suppose you get to the end of the block
and wish to index backwards.
Do you use ...
--*memory = foo;
...?
You do NOT!! You must use:
*(--memory) = foo;
Little things like this (this is a BIG, BIG bug), could
cause code to work <sometimes> and keep you awake nights.
JMODEM has been carefully written to prevent bugs like this.
It is impossible to be sure that there are no bugs in even
simple code so be careful if you modify the source.
You may modify JMODEM for your own use, but P L E A S E do
NOT distribute the modified version on BBS systems because I
do not wish to support 222,500 versions of JMODEM! If you
find a bug, or wish to improve or add something that will
increase the value of JMODEM without making it incompatible
with previous versions, please upload your improvements to
my BBS system and I may include the revisions (with your
name attached) in an upcoming version. Note that there are 6
"type" bits available in the JMODEM control-byte that could
be used to tell the receiver that another file is coming,
etc., (for batch). Things like this could be added without
destroying compatibility with previous versions.
MicroSoft C seems to have several bugs one of which affects
files that are very long (over 256k). My first attempts to
use C files under MicroSoft for JMODEM used the stream-I/O
(FILE *) type of files. This resulted in corruption of long
files. Therefore I implemented the UNIX/DOS type of file-I/O
that uses handles rather than file-control blocks. These
work rather well.
Starting with Version V3.06, The JMODEM distribution file
will no longer contain the old JMODEM.ASM source. This is to
reduce the download time. The C version is now mature enough
so that there is little or no difference between the per-
formance of JMODEM.COM, the assembly version, and
JMODEM.EXE, the C version. The original C version was about
25 k in length. It is now only about 12.
Floating point:
Originally no floating-point libraries were used. The de-
fault is still not to use any because they result in doubl-
- 15 -
JMODEM, the C Version
ing the size of the code. Some persons have complained that
the speed (cps) indication is not very accurate. This is
true because of the granularity of the time returned from
DOS (one second). If you add /DFTIME to the command-line
used to compile JMODEM_A.C in the "MAKE" file, the compiler
will use floating-point routines for the speed calculation.
The resulting JMODEM.EXE will be about 35k in length,
though, so this is a trade-off. If you wish accurate timing,
you pay for it in much-increased code-size.
Modems:
When JMODEM gets control, it turns ON CTS and DSR just in
case the BBS program has turned them off (WILDCAT does).
Some modems "hiccup" when this occurs, and the RTS line will
bounce. This caused JMODEM to "wait forever" for a RTS that
never occurs. Therefore I added a 1/2 second delay between
the time that I first set these bits and the time I start
checking for RTS and RLSD for flow-control and a possible
abort. This fixed this problem. The flow-control problem is
complex because user's might wish to transfer files between
two computers using only three wires. In such a case, there
is no flow-control and there is no modem carrier. To accom-
modate a universal solution to various hookups, JMODEM
checks for the state of DSR/CTS and RLSD when it first gets
control. If there is no carrier at this time, JMODEM will
not check for an aborted carrier during transmission or
reception. If JMODEM detects a CHANGE in either DSR or CTS,
it assumes this is flow-control and waits for these bits to
change back to whatever they were when JMODEM first obtained
control. This protocol has been used successfully since the
very first version of JMODEM. There is, however, a pos-
sibility of JMODEM wrongly interpreting what it finds if
there is "bounce" when it first gets control. That's the
reason for the delay. In any event, the normal "timeout"
trap will prevent a hung system.
BBS systems:
JMODEM still gets blamed for crashing some BBS systems even
though it is not JMODEM's fault. A common problem occurs
with systems that use compiled BASIC. Some BBS system pro-
grams assume certain characteristics about external proto-
cols and will blow up when the assumption is wrong. If you
use BASIC code that works like this:
PROTOSEND$ = "JMODEM S1 "
COMSTRING$ = PROTOSEND$+FILENAME$
SHELL COMSTRING$
- 16 -
JMODEM, the C Version
... Then JMODEM (and other protocols) will work okay.
However, If you attempt to BLOAD, CALL, or CHAIN to it, the
results will be indeterminate. This is because JMODEM
allocates memory from C runtime routines that get their
memory from DOS (not BASIC). BASIC will not "know" that its
memory has been used by the external protocol. If you exe-
cute the "SHELL" command, then you force BASIC to give up
all the memory that it can afford to spare. This free memory
is recorded by DOS and can be used for the external proto-
col.
BBS systems written is C should execute external protocols
something like this:
strcpy(command_line,"JMODEM S1 FILENAME");
system (command_line);
The C "system" command executes DOS commands from within C
programs by freeing memory and then executing COMMAND.COM.
Some C compilers don't have to load an aditional copy of
COMMAND.COM. They use an undocumented "back-door" to the
existing command interpreter! This saves memory.
This is a sneak preview of the undocumented procedure:
MOV WORD PTR [SP_SAV],SP ; Put the SP in a safe place
MOV WORD PTR [SS_SAV],SS ; Save segment registers.
MOV WORD PTR [DS_SAV],DS
MOV WORD PTR [ES_SAV],ES
MOV AX,4A00H ; Free memory
MOV BX,OFFSET TOP ; Point to the top of code
MOV CL,4 ; Bits to shift
SHR BX,CL ; Div / 16
INC BX ; Round up
INT 21H ; Free some memory
;
MOV SI,OFFSET COMMAND ; Point to the command
INT 2EH ; Make the undocumented call
CLI ; No interrupts, cleaning up
MOV DS,WORD PTR CS:[DS_SAV] ; Restore all segments
MOV ES,WORD PTR [DS_SAV]
MOV SS,WORD PTR [SS_SAV]
MOV SP,WORD PTR [SP_SAV] ; Restore stack pointer
STI ; Allow interrupts
If JMODEM and other external protocols are executed from BBS
software in this manner, then you will have no problems.
JMODEM preserves the BBS system communications environment
so BBS systems don't have to reinitialize anything when they
get control. JMODEM does not even touch the baud rate! Its
- 17 -
JMODEM, the C Version
not necessary to alter any communications parameters so it
doesn't.
A small program, SHOW.C is provided with this distribution.
It is a C program that allocates a lot of memory, writes to
the memory, then executes JMODEM.EXE using the "system"
command. After JMODEM returns from the shell, SHOW then
continues to write to memory before exiting. Since this
procedure is properly written, no system crash will occur.
You can load multiple copies of COMMAND.COM to "eat" memory.
Eventually there will be too little memory available for
JMODEM to execute. The system will still not crash.
Help:
JMODEM is now over three years old. I first wrote it in
assembly and slowly it caught on. I spent last Christmas
writing it in C. Since the C release, I have received over
500 comments from persons telling me how to make it better.
Most of these comments were from so-called professional
programmers who complained about various things. Others
complained about the comments I made about them in this
document <grin>.
Please remember that an enhancement is not a "preference".
If you prefer to do something one way or another then feel
free to modify the code for your own use. If you find a
better way to do something then please let me know.
- 18 -
JMODEM, the C Version
JMODEM revision history
The revision history has been moved to JMODEM_A.C and to
JMODEM.H (identical copies). This makes it easier to keep
the documentation current.
Version V3.08 does not do anything except make the code
comply with Microsoft's interpretation of the ANSI standard
so it will compile at their new "warning-level /W4" without
any warning errors. Jeff Jevnisek warned me about the new
C600 compiler and I had to go out and buy it. He also mod-
ified the code to be "Microsoft compliant" so, as usual,
there are no warning errors when compiling.
Microsoft, supplying over 80 percent of the 'C' compilers in
use for the PC environment, is a force that must be accom-
modated even though they are < W R O N G >, damned wrong!
Here's an example of what they now REQUIRE to pass their
"warning-level 4" test:
Given this CORRECT code....
short function (param)
short param;
{
return param;
}
... we now need this:
short function (short param)
{
return param;
}
ANSI allowed (read ALLOWED) the inclusion of the object size
(type) within the parameter list to facilitate making the
parser for the compiler. With the "old-style" method, the
size of the object was not known until the next line was
read so the compiler had to store the previous variable
names (such a pity) until it got to the line that represent-
ed the size and type of the object. Microsoft was one of the
ANSI committee representatives that insisted upon the allow-
ance for including this information within the parameter
list. It was ALLOWED by the committee. Now anything not in
conformance with Microsoft's WISH is flagged as an error!
The second problem is that the NULL object (not anything
having to do with ANSI) was previously a generic VALUE of
zero that could be assigned to any size object including
pointers of all types, ASCII string terminators, etc. This
- 19 -
JMODEM, the C Version
is no longer the case. One must cast it to the appropriate
type before use!! I got rid of all references to NULL
because it no longer has the required special character-
istics.
- finis -
- 20 -